#ifndef __PACKAGE_H__
#define __PACKAGE_H__

#include "types.h"

class EcryptionPackageV1
{
public:
    static const uint64 Magic = 0x4465734374725631ll ^ 0x12345671234567ll; // DesCtrV1
private:
#pragma pack (push, 1)
    struct DataInfo
    {
        uint64 magic = Magic;
        uint8 majorVersion = 1;
        uint8 subVersion = 0;
        uint16 reversed16 = 0;
        uint32 reversed32 = 0;
        uint64 origignalDataSize; // set by user
        uint64 ecryptedDataSize; // set by user
        byte initializeVector[8];
    };
#pragma pack (pop)
public:
    EcryptionPackageV1(const byte *packedData)
    {
        _dataInfo = reinterpret_cast<const DataInfo *>(packedData);
    }
public:
    const byte *packedData() const
    {
        return reinterpret_cast<const byte *>(_dataInfo);
    }

    const byte *ecryptedData() const
    {
        return leftData();
    }

    const byte *initializeVector() const
    {
        return _dataInfo->initializeVector;
    }

    uint64 origignalDataSize() const
    {
        return _dataInfo->origignalDataSize;
    }

    uint64 ecryptedDataSize() const
    {
        return _dataInfo->ecryptedDataSize;
    }
private:
    const byte *leftData() const
    {
        return packedData() + sizeof(DataInfo);
    }
public:
    static bool isThisPackage(const byte *data)
    {
        return *reinterpret_cast<const uint64 *>(data) == Magic;
    }

    static uint64 packagedSize(uint64 ecryptedDataSize)
    {
        return sizeof(DataInfo) + ecryptedDataSize;
    }

    static void pack(const byte *ecryptedData, byte *initializeVector, uint64 originalDataSize, uint64 ecryptedDataSize, byte *outData);

private:
    const DataInfo *_dataInfo;
};
#endif // __PACKAGE_H__